package org.cypress.rtpack.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.cypress.rtpack.entity.RtpackConfig;
import org.cypress.rtpack.mapper.RtpackConfigMapper;
import org.cypress.rtpack.service.IRtpackConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author getty
 */
@Service
public class RtpackConfigServiceImpl extends ServiceImpl<RtpackConfigMapper, RtpackConfig> implements IRtpackConfigService {

    @Override
    public RtpackConfig getByKey(String key) {
        LambdaQueryWrapper<RtpackConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RtpackConfig::getKey, key);     //RtpackConfig需要有getKey方法，类需要@Data注解
        RtpackConfig rtpackConfig = this.getBaseMapper().selectOne(queryWrapper);
        return rtpackConfig;
    }

    @Override
    public List<RtpackConfig> getAll() {
        LambdaQueryWrapper<RtpackConfig> queryWrapper = new LambdaQueryWrapper<>();
        List<RtpackConfig> rtpackConfigList = this.getBaseMapper().selectList(queryWrapper);
        return rtpackConfigList;
    }


    @Override
    public RtpackConfig updateByKey(RtpackConfig inst) {
        // 1. 参数校验
        if (inst == null || inst.getKey() == null) {
            throw new IllegalArgumentException("Config or key cannot be null");
        }

        // 2. 检查配置项是否存在
        LambdaQueryWrapper<RtpackConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RtpackConfig::getKey, inst.getKey());
        RtpackConfig existing = getOne(queryWrapper);

        if (existing == null) {
            throw new RuntimeException("Config with key [" + inst.getKey() + "] not found");
        }

        // 3. 保留原始ID（防止前端误传ID导致更新错误记录）
        //config.setId(existing.getId());

        // 4. 执行更新（MyBatis-Plus的updateById是原子操作）
        boolean success = updateById(inst);

        if (!success) {
            throw new RuntimeException("Update config failed");
        }

        // 5. 返回更新后的完整数据（避免返回前端可能修改过的对象）
        return getByKey(inst.getKey());
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务控制
    public List<RtpackConfig> batchUpdateByKey(List<RtpackConfig> instList) {
        // 1. 参数校验
        if (CollectionUtils.isEmpty(instList)) {
            throw new IllegalArgumentException("Config list cannot be empty");
        }

        // 2. 检查所有key是否存在
        List<String> keys = instList.stream()
                .map(RtpackConfig::getKey)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (keys.size() != instList.size()) {
            throw new IllegalArgumentException("Some configs have null keys");
        }

        // 3. 获取现有配置项映射表（一次性查询优化性能）
        Map<String, RtpackConfig> existingMap = listByKeys(keys).stream()
                .collect(Collectors.toMap(RtpackConfig::getKey, Function.identity()));

        // 4. 准备待更新列表（保留原始ID）
        List<RtpackConfig> toUpdate = instList.stream()
                .peek(config -> {
                    RtpackConfig existing = existingMap.get(config.getKey());
                    if (existing == null) {
                        throw new RuntimeException("Config with key [" + config.getKey() + "] not found");
                    }
                    config.setKey(existing.getKey()); // 关键：绑定数据库ID
                })
                .collect(Collectors.toList());

        // 5. 批量更新（MyBatis-Plus的saveOrUpdateBatch）
        if (!updateBatchById(toUpdate)) {
            throw new RuntimeException("Batch update failed");
        }

        // 6. 返回更新后的最新数据
        return (List<RtpackConfig>) listByIds(toUpdate.stream().map(RtpackConfig::getKey).collect(Collectors.toList()));
    }

    // 辅助方法：根据keys批量查询
    private List<RtpackConfig> listByKeys(List<String> keys) {
        LambdaQueryWrapper<RtpackConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RtpackConfig::getKey, keys);
        return list(queryWrapper);
    }
}
